# coding=utf-8
import json
import time

import allure
from common.assert_operator import *
from common.db import *
from common.read_yaml import *
from common.utils import Utils

string_assert = string_assert() # 字符串校验类
pact = Pact() # 契约校验类
execute_sql = sql() # sql集合
utils = Utils()
data = ReadYaml_By_Root_Dict("case/99_outside_api_test/02_bpm_outside_test/99_02_4_GetProcessInstanceStepsView_ApprovalInvalid.yml").get_yaml_data()  # 读取数据

def query_history_table(BussinessGUID,node=",ne.Id '节点GUID'"):
    sql = f"""SELECT spe.ActivityOrder '序号',spe.ActivityName '步骤名称',ne.OrderCode '节点序号', pe.Id '流程GUID',pe.ProcessName '流程名称', ne.AssignedToUserName '责任人' ,ne.TaskState '节点状态', spe.ActivityState '步骤状态',pe.ProcessState '流程状态'{node},u.code '用户code'
                            FROM dbo.WfProcessInstanceHistory pe With (NoLock) JOIN dbo.WfTasksHistory ne With (NoLock) ON pe.Id = ne.ProcessInstanceID 
                            LEFT JOIN dbo.p_user u With (NoLock) ON u.id =ne.AssignedToUserID 
                            JOIN dbo.WfActivityInstanceHistory spe With (NoLock) ON spe.ProcessInstanceID = ne.ProcessInstanceID AND ne.ActivityInstanceID=spe.Id
                            WHERE pe.BusinessKey = '{BussinessGUID}' ORDER BY spe.ActivityOrder,ne.OrderCode;"""
    return sql


@allure.feature('测试流程中心外部接口：获取流程步骤审批记录，BPM作废流程')  # 测试报告显示测试功能
class Test_99_02_4_GetProcessInstanceStepsView_ApprovalInvalid():
    """
    测试接口：
    /api/flowinstance/approval/get-process-instance-steps-view
    /api/flowinstance/approval/invalid
    /api/third-party-auth/get-verify-token?app_id={client_id}
    /api/third-party-auth/get-token?app_id={client_id}
    /api/flowinstance/approval/cancel-process
    """
    # 获取yml文件中[获取流程步骤审批记录]的数据参数
    Params = data['获取流程步骤审批记录']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(Params, "$[*][0]")
    @pytest.mark.parametrize("title, param, expect", Params, ids=ids_list)
    def test_GetProcessInstanceStepsView(self, user_login, title, param, expect):
        allure.dynamic.description(f"{param['用例描述']}")  # # 动态解析用例描述在测试报告中展示
        main = user_login.goto_Bpm_Outside_Api(param['用户'])
        resp = main.get_process_instance_steps_view(param['请求体'])
        resp_json = resp.json()
        ProcessInstance = jsonpath.jsonpath(resp_json, "$.data.ProcessInstance")[0]
        dict_assert(expect['响应校验'], ProcessInstance)  # 结果断言
        # 校验ProcessInstance获取方式，执行后，日志输出中，搜索响应实际值，查看响应实际值
        ProcessInstance = json.dumps(ProcessInstance, ensure_ascii=False)
        Logger.debug(f"响应校验实际值:\n{ProcessInstance}")
        # # 得到审批历时节点的path路径：[['data', 'ActualPath', '0', 'nodes', '0']]
        # IPATH = jsonpath.jsonpath(resp.json(), '$.data.ActualPath[*].nodes[?(@.spend_time_display!="")]',
        #                           'IPATH')  # 得到路径
        # # 使用json.dumps将字典转换为JSON格式的字符串
        # json_str = json.dumps(resp_json)
        # if IPATH:  # 存在路径则进行删除历时值的操作
        #     # 通过jsonpath，更新掉spend_time_display的值，此值是历时时间，每次查询都会变动
        #     utils.update_json_by_jsonpath(resp_json,'$.data.ActualPath[*].nodes[?(@.spend_time_display!="")]','')
        #     utils.update_json_by_jsonpath(expect['响应校验'],'$.data.ActualPath[*].nodes[?(@.spend_time_display!="")]','')
        #     # 响应校验获取方式：开启fiddler，执行用例后，直接获取fiddler的响应body
        #     dict_assert(expect['响应校验'], resp_json)  # 结果断言
        #     Logger.debug(f"响应校验实际值:\n{json_str}")
        # else:
        #     # 响应校验获取方式：开启fiddler，执行用例后，直接获取fiddler的响应body
        #     dict_assert(expect['响应校验'], resp_json)  # 结果断言
        #     Logger.debug(f"响应校验实际值:\n{json_str}")


    # 获取yml文件中[获取流程步骤审批记录_异常场景]的数据参数
    Params = data['获取流程步骤审批记录_异常场景']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(Params, "$[*][0]")
    @pytest.mark.parametrize("title, param, expect", Params, ids=ids_list)
    def test_GetProcessInstanceStepsView_Abnormal(self, user_login, title, param, expect):
        allure.dynamic.description(f"{param['用例描述']}")  # # 动态解析用例描述在测试报告中展示
        main = user_login.goto_Bpm_Outside_Api(param['用户'])
        resp = main.get_process_instance_steps_view(param['请求体'])
        dict_assert(expect['响应校验'],resp.json())    # 结果断言


    # 获取yml文件中[外部接口作废流程]的数据参数
    Params = data['外部接口作废流程']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(Params, "$[*][0]")
    @pytest.mark.parametrize("title, param, expect", Params, ids=ids_list)
    def test_Outside_Invalid(self, user_login, title, param, expect):
        allure.dynamic.description(f"{param['用例描述']}")  # # 动态解析用例描述在测试报告中展示
        user, BussinessGUID, OtherParams = param['用户'],param['业务GUID'], param['其他参数']
        main = user_login.goto_Bpm_Outside_Api(user)
        resp = main.approval_invalid(user, BussinessGUID, OtherParams)
        dict_assert(expect['响应校验'],resp.json())    # 结果断言
        # 作废后，查询数据库结果
        sql = query_history_table(BussinessGUID)
        result = sqlserver_query_return_contain_field(sql)
        if len(result)==1:
            result = utils.query_until_column_value_matched(sql,'序号','==','000')
        list_each_equal(expect['数据库校验'],result)


    # 获取yml文件中[外部接口作废流程_异常场景]的数据参数
    Params = data['外部接口作废流程_异常场景']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(Params, "$[*][0]")
    @pytest.mark.parametrize("title, param, expect", Params, ids=ids_list)
    def test_Outside_Invalid_Abnormal(self, user_login, title, param, expect):
        allure.dynamic.description(f"{param['用例描述']}")  # # 动态解析用例描述在测试报告中展示
        user, BussinessGUID, OtherParams = param['用户'], param['业务GUID'], param['其他参数']
        main = user_login.goto_Bpm_Outside_Api(user)
        resp = main.approval_invalid(user, BussinessGUID, OtherParams)
        dict_assert(expect['响应校验'], resp.json())  # 结果断言

    # 获取yml文件中[获取verify_token]的数据参数
    Params = data['获取verify_token']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(Params, "$[*][0]")
    @pytest.mark.parametrize("title, param, expect", Params, ids=ids_list)
    def test_GetVerifyToken(self, user_login, title, param, expect):
        allure.dynamic.description(f"{param['用例描述']}")  # # 动态解析用例描述在测试报告中展示
        user, body = param['用户'], param['请求体']
        main = user_login.goto_Bpm_Outside_Api(user)
        resp = main.get_verify_token(user, body)
        # 契约校验
        contract_format = Matcher({
            "code": 1,
            "data": Matcher({
                "token": Term(r'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.*',example="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwcm9jZXNzV2l0aG91dFZlcmlmeSI6IjYxODFlODU4NzUxYjAzOTQzNTIwNzkzOTUyODU1NTgwIn0.c4SmTx1Dr4zNjF6w_t-vjLaWRcm_IT8ZsliFMHXqjwY")
            }),
            "message": "",
            "detailMessage": "",
            "success": 1
        })
        pact.pact_verify(contract_format,resp.json())

    # 获取yml文件中[第三方服务授权]的数据参数
    Params = data['第三方服务授权']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(Params, "$[*][0]")
    @pytest.mark.parametrize("title, param, expect", Params, ids=ids_list)
    def test_AccessToken(self, user_login, title, param, expect):
        allure.dynamic.description(f"{param['用例描述']}")  # # 动态解析用例描述在测试报告中展示
        user, body = param['用户'], param['请求体']
        main = user_login.goto_Bpm_Outside_Api(user)
        resp = main.access_token(user, body)
        # 契约校验
        contract_format = Matcher({
            "code": 1,
            "data": Matcher({
                "token": Term(r'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.*',
                              example="eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJwcm9jZXNzV2l0aG91dFZlcmlmeSI6IjYxODFlODU4NzUxYjAzOTQzNTIwNzkzOTUyODU1NTgwIn0.c4SmTx1Dr4zNjF6w_t-vjLaWRcm_IT8ZsliFMHXqjwY")
            }),
            "message": "",
            "detailMessage": "",
            "success": 1
        })
        pact.pact_verify(contract_format, resp.json())

    # 获取yml文件中[业务接口作废]的数据参数
    Params = data['业务接口作废']
    # 获取yml的title，并作为ids的值传给用例
    ids_list = jsonpath.jsonpath(Params, "$[*][0]")
    @pytest.mark.parametrize("title, param, expect", Params, ids=ids_list)
    def test_ApprovalInvalid(self, user_login, title, param, expect):
        allure.dynamic.description(f"{param['用例描述']}")  # # 动态解析用例描述在测试报告中展示
        user, body = param['用户'], param['请求体']
        RespVerify,DBVerify = "响应校验","数据库校验"
        main = user_login.goto_Bpm_Outside_Api(user)
        resp = main.cancel_process(body)
        BussinessGUID = body['businessGuid']
        dict_assert(expect[RespVerify],resp.json())    # 结果断言
        # 作废后，查询数据库结果
        sql = query_history_table(BussinessGUID,node="")    # 查询结果不包含节点ID，作废归档流程时，结束步骤节点ID会变动
        result = sqlserver_query_return_contain_field(sql,DBVerify)
        if len(result)==1:
            result = utils.query_until_column_value_matched(sql,'序号','==','000')
        list_each_equal(expect[DBVerify],result)   # 校验作废后数据库结果